package com.bytz.modules.cms.order.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bytz.common.exception.BytzBootException;
import com.bytz.common.util.mentity.EntityMergeInfoV2;
import com.bytz.common.util.mentity.util.MergeEntityUtil;
import com.bytz.modules.cms.order.constant.OrderConstants;
import com.bytz.modules.cms.order.entity.Order;
import com.bytz.modules.cms.order.entity.OrderDesignFlowRule;
import com.bytz.modules.cms.order.entity.OrderFlowRule;
import com.bytz.modules.cms.order.entity.OrderItem;
import com.bytz.modules.cms.order.mapper.OrderFlowRuleMapper;
import com.bytz.modules.cms.order.model.AdminOrderModel;
import com.bytz.modules.cms.order.model.OrderItemModel;
import com.bytz.modules.cms.order.service.IOrderFlowRuleService;
import com.bytz.modules.cms.order.util.ScriptEvalUtil;
import org.springframework.stereotype.Service;

import javax.script.Bindings;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 订单流程规则服务
 *
 * @author shanxuezhong
 */
@Service
public class OrderFlowRuleServiceImpl extends ServiceImpl<OrderFlowRuleMapper, OrderFlowRule> implements IOrderFlowRuleService {
    @Override
    public Map<String, Boolean> runForFlow(AdminOrderModel order, List<OrderItemModel> orderItems) {
        Bindings bindings = ScriptEvalUtil.createBinding(order, orderItems);

        return getAllRuleForRun().stream()
                .collect(Collectors.toMap(OrderFlowRule::getFlowVarName,
                        v -> !evalScript(v.getId(), v.getScript(), bindings, v.getActivityName())));
    }

    @Override
    public void publish(List<OrderDesignFlowRule> allScripts) {
        List<OrderFlowRule> orderFlowRules = BeanUtil.copyToList(allScripts, OrderFlowRule.class);

        EntityMergeInfoV2<OrderFlowRule> entityMergeInfo = MergeEntityUtil.calculateEntityMergeInfo(orderFlowRules, list());
        MergeEntityUtil.doDbMerge(entityMergeInfo, this);
    }

    @Override
    public List<OrderFlowRule> getAll() {
        return list();
    }

    /**
     * 获取全部用于运行的脚本对象
     */
    private List<OrderFlowRule> getAllRuleForRun() {
        List<OrderFlowRule> list = list();
        String globalScript = list.stream()
                .filter(p -> OrderConstants.OrderFlowRuleType.GLOBAL.equals(p.getType()))
                .findFirst()
                .map(OrderFlowRule::getScript)
                .orElse("");

        return list.stream()
                .filter(p -> OrderConstants.OrderFlowRuleType.PRIVATE.equals(p.getType()))
                .peek(p -> p.setScript(globalScript + "\r\n" + p.getScript()))
                .collect(Collectors.toList());
    }

    private Boolean evalScript(String scriptId, String script, Bindings bindings, String activityName) {
        try {
            return treatEvalResult(ScriptEvalUtil.evalScript(scriptId, script, bindings));
        } catch (Exception e) {
            throw new BytzBootException("计算节点【" + activityName + "】脚本出错：" + e.getMessage(), e);
        }
    }

    private Boolean treatEvalResult(Object result) {
        if (result instanceof Boolean) {
            return (Boolean) result;
        } else {
            throw new BytzBootException("结果不是布尔型");
        }
    }
}